const Parse = require('parse/node');
const _=require('lodash');
const config=require("../config/config");
const template_file = config.template_file;
const NameListObj = Parse.Object.extend("v5_name_list");
const ParseHelper = require('../helpers/parse');
const ExcelService = require("./excel");

//从excel文件中导入多个名单
async function importNameListFromExcelFile(filePath,dataColumnNumber=1,firstDataRowNumber=2){
    const nameListDict=await ExcelService.parseExcelFileNameLists(filePath,dataColumnNumber,firstDataRowNumber);
    return importNameListDict(nameListDict);
}

//使用名单字典导入多个名单到数据库，返回创建的名单数与更新的名单数
//输入样例:{ Sheet1: [ '111', '222' ], Sheet2: [ 'aa', 'bb', 'cc' ] }
//输出样例:{createCount:1,updateCount:1}
async function importNameListDict(nameListDict){
    const nameListNames=Object.keys(nameListDict);
    //查询数据库中同名的名单
    const query = new Parse.Query(NameListObj);
    query.notEqualTo('isDeleted', true);
    query.containedIn('name', nameListNames);
    const existNameListObjs= await query.find({ useMasterKey: true });
    //更新已有名单
    existNameListObjs.forEach(nameListObj=>{
        const name=nameListObj.get("name");
        nameListObj.set("usernames",nameListDict[name]);
        _followNameList(nameListObj.get("followers"),nameListObj.get("usernames"));
    });
    const existNameListNames=existNameListObjs.map(o=>o.get("name"));
    //创建新名单
    const newNameListObjs=[];
    nameListNames.forEach(name=>{
        if(existNameListNames.indexOf(name)<0){
            const nameList = new NameListObj();
            nameList.set("name",name);
            nameList.set("usernames", nameListDict[name]);
            nameList.set("followers",{});//初始化名单跟踪
            newNameListObjs.push(nameList);
        }
    });
    //合并数据，执行更新
    const allNameListObjs=[...existNameListObjs,...newNameListObjs];
    await Parse.Object.saveAll(allNameListObjs,{ useMasterKey: true });
    //返回创建的名单数与更新的名单数
    return {createCount:newNameListObjs.length,updateCount:existNameListObjs.length}
}

//根据跟踪字段对其他表进行更新
async function followNameList(nameListId){
    const query = new Parse.Query(NameListObj);
    const obj=await query.get(nameListId,{ useMasterKey: true });
    if(obj){
        return _followNameList(obj.get("followers"),obj.get("usernames"));
    }
}

//根据跟踪字段对其他表进行更新
//followers:{objectId:{table,fields:[field1,field2]}}
//usernames:用于复制的名单
async function _followNameList(followers,usernames){
    const updates=Object.keys(followers).map(objectId=>{
        const follower=followers[objectId];
        const TableObj = Parse.Object.extend(follower.table);
        const tableObj=TableObj.createWithoutData(objectId);
        follower.fields.forEach(field=>{
            tableObj.set(field,usernames);
        });
        return tableObj.save(null,{ useMasterKey: true });
    });
    return Parse.Object.saveAll(updates,{ useMasterKey: true });
}

//添加名单跟随
//nameListName:要跟随的名单Id,objectId:跟随名单的记录Id,table:跟随名单的表,fields：跟随名单的字段名数组
async function setFollowers(nameListId,followerId,table,fields){
    const nameListObj=NameListObj.createWithoutData(nameListId);
    nameListObj.set(`followers.${followerId}`,{table,fields});
    return nameListObj.save(null,{ useMasterKey: true });
}

//去除名单跟随
async function unsetFollowers(nameListId,followerId){
    const nameListObj=NameListObj.createWithoutData(nameListId);
    nameListObj.unset(`followers.${followerId}`);
    return nameListObj.save(null,{ useMasterKey: true });
}

//创建名单
async function add(name,usernames,owner){
    const nameListObj=new NameListObj({name,usernames,owner,followers:{}});
    await nameListObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(nameListObj);
}

//删除
async function remove(nameListId){
    const nameListObj=NameListObj.createWithoutData(nameListId);
    nameListObj.set("isDeleted",true);
    await nameListObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(nameListObj);
}


//添加成员到名单
async function add_user(nameListId,username){
    const nameListObj=NameListObj.createWithoutData(nameListId);
    nameListObj.addUnique("usernames",username);
    await nameListObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(nameListObj);
}

//从名单中删除成员
async function remove_user(nameListId,username){
    const nameListObj=NameListObj.createWithoutData(nameListId);
    nameListObj.remove("usernames",username);
    await nameListObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(nameListObj);
}

async function update(id,key,value){
    const nameListObj= NameListObj.createWithoutData(id);
    nameListObj.set(key,value);
    await nameListObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(nameListObj);
}

//检查用户数据是否合规,有错误返回错误原因，
/*
result={
error:"错误原因", //无错误时无此项
exampleRows, //样例数据，前5行
mappedExampleRows, //对字段进行映射的样例数据
filePath, //文件路径
count //数据行数
}
 */
async function checkExcelFile(filePath,nameRowNumber,firstDataRowNumber,fieldsMapping){
    const usersData=await ExcelService.parseExcelFileFirstSheet(filePath,nameRowNumber,firstDataRowNumber);
    if(usersData.length>0){
        //取得前5行作为样例数据
        var exampleRows=_.take(usersData,5);
        var needDeleteExtra = false;
        if(template_file==='users_kmust.xlsx'||template_file==='users_seu.xlsx'){
            needDeleteExtra = true;
            exampleRows = exampleRows.map(u=>addYHM(u));
        }
        var mappedExampleRows=exampleRows.map(row=>mappingUserData(row,fieldsMapping,needDeleteExtra));
        const result={
            exampleRows,
            mappedExampleRows,
            filePath,
            count:usersData.length
        };
        if(!mappedExampleRows[0].hasOwnProperty("username")||!mappedExampleRows[0].hasOwnProperty("class_name")){
            result.error= "缺少用户名或班级字段"
        }
        return result;
    }else{
        return {error:'文件内容为空'};
    }
}

//根据fieldsMapping修改userData中的key
function mappingUserData(userData, fieldsMapping,needDeleteExtra=false){
    const mappedUserData={...userData};//复制要处理的数据
    Object.keys(mappedUserData).forEach(function(key) {
        const dbFieldName=fieldsMapping[key];
        if(dbFieldName){
            mappedUserData[dbFieldName] = mappedUserData[key];
            delete mappedUserData[key];
        }else{
            if(needDeleteExtra===true){
                delete mappedUserData[key];
            }
        }
    });
    return mappedUserData;
}

function addUsername(user){
    if(!user.hasOwnProperty("username")&&user.hasOwnProperty("studentNumber")){
        user["username"]=user.studentNumber;
    }
    return user;
}

function addYHM(user){
    if(!user.hasOwnProperty("用户名")&&user.hasOwnProperty("学号")){
        user["用户名"]=user.学号;
    }
    return user;
}

async function importExcelFile(filePath,nameRowNumber,firstDataRowNumber,fieldsMapping,owner){
    var usersData=await ExcelService.parseExcelFileFirstSheet(filePath,nameRowNumber,firstDataRowNumber);
    var needDeleteExtra = false;
    if(template_file==='users_kmust.xlsx'||template_file==='users_seu.xlsx'){
        needDeleteExtra = true;
        usersData = usersData.map(u=>addYHM(u));
    }
    var mappedUsersData=usersData.map(ud=>mappingUserData(ud,fieldsMapping,needDeleteExtra));
    const classMembersDict = _.groupBy(mappedUsersData,'class_name');
    const class_names=Object.keys(classMembersDict);
    const result = class_names.map(async class_name => {
        const members = classMembersDict[class_name];
        const usernames = members.map(member => member.username);
        const difUsernames = _.uniq(usernames);

        const query = new Parse.Query(NameListObj);
        query.equalTo('owner', owner);
        query.equalTo('name', class_name);
        query.notEqualTo('isDeleted', true);
        query.select('usernames');
        const oriNameList = await query.first({useMasterKey: true});
        if(oriNameList){
            const jsonOriNameList = ParseHelper.toJSON(oriNameList);
            const oriStudents = jsonOriNameList.usernames||[];//数据库原始数据
            const newNameList = NameListObj.createWithoutData(id);
            difUsernames.forEach(username=>{
                newNameList.addUnique('usernames',username);
            });
            return await newNameList.save(null,{ useMasterKey: true });
        }else{
            //创建新的
            const nameListObj = new NameListObj({name: class_name, usernames: difUsernames, owner, followers: {}});
            return await nameListObj.save(null, {useMasterKey: true});
        }
    });
    const all_namelists = await Promise.all(result);
    return {successCount:all_namelists.length};
}

module.exports={
    importNameListFromExcelFile,
    setFollowers,
    unsetFollowers,
    followNameList,
    add,
    remove,
    add_user,
    remove_user,
    update,
    checkExcelFile,
    importExcelFile
};